#include "Bag.h"

bool Bag::addItem(int16_t pos, Item::PTR item)
{
    if (isValidPos(pos))
    {
        mItems[pos] = item;
        return true;
    }
    else
    {
        return false;
    }
}

void Bag::removeByPos(int16_t pos)
{
    if (isValidPos(pos))
    {
        mItems[pos] = nullptr;
    }
}

void Bag::resize(size_t size)
{
    if (size >= mItems.size())
    {
        mItems.resize(size, nullptr);
    }
}

Item::WEAK_PTR Bag::getItemByPos(int16_t pos)
{
    if (isValidPos(pos))
    {
        return mItems[pos];
    }
    else
    {
        return Item::WEAK_PTR();
    }
}

int16_t Bag::getCapacity() const
{
    return mItems.capacity();
}

bool Bag::isValidPos(int16_t pos) const
{
    return pos >= 0 && pos < mItems.size();
}

rapidjson::Value Bag::packToJson(rapidjson::Document& doc) const
{
    rapidjson::Value value(rapidjson::kObjectType);

    rapidjson::Value allitems(rapidjson::kArrayType);

    int pos = 0;
    for (auto& v : mItems)
    {
        pos++;

        if (v)
        {
            rapidjson::Value oneItem(rapidjson::kObjectType);
            rapidjson::Value dynamicValue(rapidjson::kObjectType);
            packDatabackToJson(dynamicValue, doc, *v);

            oneItem.AddMember("tID", v->getTypeID(), doc.GetAllocator());
            oneItem.AddMember("pos", pos, doc.GetAllocator());
            oneItem.AddMember("dynamicAttr", dynamicValue, doc.GetAllocator());

            allitems.PushBack(oneItem, doc.GetAllocator());
        }
    }

    value.AddMember("items", allitems, doc.GetAllocator());
    value.AddMember("size", mItems.capacity(), doc.GetAllocator());

    return value;
}

void Bag::unpackFromJson(rapidjson::Value& value)
{
    const rapidjson::Value& items = value["items"];
    const rapidjson::Value& size = value["size"];

    resize(size.GetInt());

    for (size_t i = 0; i < items.Size(); ++i)
    {
        const rapidjson::Value& oneItem = items[i];

        Item::PTR item = std::make_shared<Item>(oneItem["tID"].GetInt());
        unpackJsonToDatabank(oneItem["dynamicAttr"], *item);

        addItem(oneItem["pos"].GetInt(), item);
    }
}

int Bag::countItemNum(int16_t id)
{
    int n = 0;
    for(std::vector<Item::PTR>::iterator it = mItems.begin(); it != mItems.end(); ++it)
    {
        if((*it) != nullptr && (*it)->getTypeID() == id)
        {
            n++;
        }
    }
    return n;
}

std::vector<int16_t> Bag::delItems(int16_t id, int n)
{
    std::vector<int16_t> ret;
    for (int i = 0; i < mItems.size(); ++i)
    {
        Item::PTR item = mItems[i];
        if (item != nullptr && item->getTypeID() == id)
        {
            mItems[i] = nullptr;
            ret.push_back(i);
            if (mItems.size() >= n)
            {
                break;
            }
        }
    }

    return ret;
}

int Bag::findEmptyPos()
{
    for (int i = 0; i < mItems.size(); ++i)
    {
        if (mItems[i] == nullptr)
        {
            return i;
        }
    }

    return -1;
}
